<?php
/**
 * zen_menu_gtk.php
 * @author Juan Belon
 * @access public
 * @copyright LGPL, GPL
 * @package zenphp_generador
 * @version 0.1.1
 * @uses zenphp FrameWork
 * @link http://csl2-zenphp.forja.rediris.es
 * @link http://www.zenphp.es
 * @link https://forja.rediris.es/projects/csl2-zenphp/
 * @see zen_ventana_principal
 * @magic Genera un menú para la ventana principal del generador que está definido en un XML
 */
// +----------------------------------------------------------------------
// | zenphp.es
// +----------------------------------------------------------------------
class zen_menu_gtk extends GtkMenuBar {
	/**
	* Objeto que se puede consturir a partir de una Cadena XML que lee el objeto DOMDocument o bien
	* desde una ruta de un fichero. Funciones para ello: $this->crear_desde_cadena($cadena_xml) o 
	* $this->crear_desde_xml($fichero)
	* @var DOMDocument
	*/
	var $xml;
	/**
	* Conjunto de widgets que componen el menú de la aplicación
	* @var array
	*/
	var $widgets = array();
	/**
	* Bandera para añadir un menú GTK para desprender los menús de su posición original y colocarlos
	* donde quiera el usario
	* @var bool
	*/
	var $anadirEnganches = true;
	/**
	* Ventana principal del generador de aplicaciones donde se colocan los menús
	* @var zen_ventana_principal
	*/
	var $ventana_principal;
        /**
        * Para construir todas las conexiones con los eventos asociados a cada menú
        * @var $nombres_menus
        */
        var $nombres_menus = array();
        /**
        * Fábrica de componentes GTK de la ventana principal asociada
        * @var zen_fabrica_gtk
        */
        var $fabrica;
        /**
        * Constructor de menús
        * @return zen_menu_gtk
        */
        function zen_menu_gtk(&$ventana_principal) {
          parent::__construct();
          $this->ventana_principal =& $ventana_principal;
          $this->fabrica =& $this->ventana_principal->fabrica;
	}
        /**
        * Llama a loadXML de DOMDocument con la $cadena XML
        * e intenta construir el menú de la aplicación que se define en dicha cadena
        * @param str $cadena
        */
	function crear_desde_cadena($cadena) {
		$this->xml = DOMDocument::loadXML($cadena);
		$this->inicio_construir();
	}
        /**
        * Llama a load de DOMDocument con el $fichero XML
        * e intenta construir el menú de la aplicación que se define en dicho fichero
        * @param str $fichero
        */
	function crear_desde_xml($fichero) {
		$this->xml = DOMDocument::load($fichero);
		$this->inicio_construir();
	}
	/**
	* Valida la cadena pasada o leida de un fichero y almacenada en el objeto $this->xml y
	* construye los menús a partir de los nodos que se definen en la estructura XML
	*/
	function inicio_construir() {
		if ($this->xml->validate()) {
		 $nodos = $this->xml->documentElement->childNodes;
		 $this->construir($this, $nodos);
		} else {
		 throw new Exception("Formato del XML incorrecto.");
		//trigger_error("Formato del XML incorrecto.");
		}
	}
        /**
        * Recorre los $nodos y con el objeto $obj va construyendo cada uno de sus items dentro del contenedor menú
        * @param zen_menu_gtk $obj
        * @param object $nodos
        */
	function construir($obj, $nodos) {
		foreach ($nodos as $nodo) {
			if ($nodo->nodeType != 1)
			 continue;
			$ret = $this->construirItems($nodo);
			$obj->append($ret);
		}
	}
        /**
        * Construye los items de un menú mediante la clase zen_fabrica_gtk
        * @param object $nodo
        * @param str $tipo
        * @return GtkImageMenuItem
        */
	function construirItems($nodo, $tipo = null) {
		$fabrica =& $this->fabrica;

		if (!$tipo)
		 $tipo = $nodo->nodeName;
		$id = $nodo->getAttribute("id");
                
		if ($tipo != "separador" && is_null($id)) {
		  throw new Exception("Item sin id");
		 //trigger_error("Item sin id");
		}

		$mostrar  = $nodo->getAttribute("mostrar");
		$icono    = $nodo->getAttribute("icono");
		$enganche = $nodo->getAttribute("arrancable") == "true";

		switch ($tipo) {
			case "item":
				if (!is_null($mostrar)) {
					if (!is_null($icono)) {
						$item = $fabrica->imagen_menuItem($mostrar);
						$imagen = $fabrica->icono($icono);
						$item->set_image($imagen);
					} else {
						$item = $fabrica->menuItem($mostrar);
					}
				} else if (!is_null($icono)) {
					$item = $fabrica->imagen_menuItem($icono);
				} else {
				 //trigger_error("Cada item debe tener al menos un icono o un texto para mostrar");
					throw new Exception("Cada item debe tener al menos un icono o un texto para mostrar");
				}
				$this->registrar($id, $item);
                                if (!$enganche && !is_null($id)){
                                  array_push($this->nombres_menus,$id);
                                }
				return $item;

			case "separador":
				return $fabrica->separadorItem();
			default:
				$menu = $fabrica->menu();
				if ($enganche && $this->anadirEnganches)
					$menu->append($fabrica->enganche());
				$this->construir($menu, $nodo->childNodes);
				$item = $this->construirItems($nodo, "item");
				$item->set_submenu($menu);

				return $item;
		}
	}
        /**
        * Registra un widget, un objeto $obj con su $id, lo almacena en el array local $this->widgets
        * @param str $id
        * @param Object $obj
        */
	function registrar($id, $obj) {
		if (!array_key_exists($id, $this->widgets))
		 $this->widgets[$id] = $obj;
		else
		 //trigger_error("Ya hay un widget con ese ID");
		 throw new Exception("Ya hay un widget con ese ID");
	}
        /**
        * Devuelve el Objeto con el $id especificado
        * @param str $id
        * @return Object
        */
	function obtenerWidget($id) {
		if (array_key_exists($id, $this->widgets))
		 return $this->widgets[$id];
		else return null;
	}
        /**
        * Establece la bandera de añadir los elementos de enganche de un menú GTK, para
        * poder separarlos de la ventana y mostrarlos en una ventana separada
        * @param bool $anadir
        */
	function anadirEnganches($anadir=true) {
		$this->anadirEnganches = $anadir;
	}
}
?>